#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
# Description: Main build script for liblinux
# Author: Huawei OS Kernel Lab
# Create: Mon Oct 18 15:06:50 2021

set -e

# cleanup conflict envs
export SRCTREE=""
export MAKEFLAGS=""
export SRC=""
export MFLAGS=""
export KBUILD_SRC=""
export KCONFIG_CONFIG=.config
export LOCALVERSION=""

# hack for run build.sh directly
[ -z "$ARCH" ]			&& export ARCH=arm64
[ -z "$CROSS_COMPILE" ]		&& export CROSS_COMPILE=aarch64-euler-elf-
[ -z "$EXTLIB_SRC" ]		&& export EXTLIB_SRC=$(pwd)
[ -z "$EXTLIB_OUTPUT" ]		&& export EXTLIB_OUTPUT=$(pwd)
[ -z "$EXTLIB_TARGET" ]		&& export EXTLIB_TARGET=${EXTLIB_OUTPUT}/liblinux.a
[ -z "$_MAKE" ]			&& export _MAKE="make -j"
[ -z "$AR" ]			&& export AR=${CROSS_COMPILE}ar
[ -z "$CC" ]			&& export CC=${CROSS_COMPILE}gcc
[ -z "$LD" ]			&& export LD=${CROSS_COMPILE}ld
[ -z "$NM" ]			&& export NM=${CROSS_COMPILE}nm
[ -z "$STRIP" ]			&& export STRIP=${CROSS_COMPILE}strip

# hack for aarch64 -> arm64
[ "${ARCH}" = "aarch64" ] && export ARCH="arm64"

# select defconfig by ${ARCH} and ${SUBARCH}
if [ "${ARCH}" = "arm64" ]; then
	if [ "${SUBARCH}" = "be" ]; then
		LIBLINUX_DEFCONFIG="liblinux_be_defconfig"
	else
		LIBLINUX_DEFCONFIG="liblinux_le_defconfig"
	fi
elif [ "${ARCH}" = "arm" ]; then
	if [ "${SUBARCH}" = "be" ]; then
		LIBLINUX_DEFCONFIG="liblinux_be_defconfig"
	else
		LIBLINUX_DEFCONFIG="liblinux_le_defconfig"
	fi
else
	echo "Unknown ARCH ${ARCH}"
	exit
fi

if [ -z "${DEFCONFIG}" ]; then
	DEFCONFIG=${LIBLINUX_DEFCONFIG}
fi

merge_defconfig()
{
	CFG_LIST=()
	SRC=$(cd $(dirname $0); pwd)

	for cfg in "${KCONFIG_ADD_ON[@]}"; do
		CFG_LIST+=("${SRC}/arch/$ARCH/configs/$cfg")
	done

	pushd ${EXTLIB_OUTPUT}
	${SRC}/scripts/kconfig/merge_config.sh -m .config ${CFG_LIST[@]}
	${_MAKE} CC="${CC}" olddefconfig
	popd
}

# generate .config if not exists
if [ ! -f "${EXTLIB_OUTPUT}/.config" ]; then
	${_MAKE} CC="${CC}" -C ${EXTLIB_SRC} O=${EXTLIB_OUTPUT} ${DEFCONFIG}
	if [ ! -z "${KCONFIG_ADD_ON}" ]; then
		merge_defconfig
	fi
fi

# build vmlinux
${_MAKE} -C ${EXTLIB_OUTPUT} KBUILD_LIBLINUX_FILTER_OBJS=1 CC="${CC}" vmlinux

# generate liblinux.a
printf "  %-7s %s\n" AR liblinux.a

if [ -f "${EXTLIB_TARGET}" ]; then
	rm ${EXTLIB_TARGET}
fi

VMLINUX_ADDITIONAL=("")
add_vmlinux_additional()
{
	local symbol=$1
	local obj=$2
	local ret=0
	${NM} ${EXTLIB_OUTPUT}/vmlinux | grep ${symbol} 1>/dev/null 2>&1 || ret=$?
	if [ $ret -ne 0 ]; then
		VMLINUX_ADDITIONAL+=("${obj}")
	fi
}
add_vmlinux_additional fdt_create_empty_tree ${EXTLIB_OUTPUT}/lib/fdt_empty_tree.o
add_vmlinux_additional fdt_strerror ${EXTLIB_OUTPUT}/lib/fdt_strerror.o
add_vmlinux_additional fdt_finish ${EXTLIB_OUTPUT}/lib/fdt_sw.o

${AR} -rcs ${EXTLIB_TARGET} ${EXTLIB_OUTPUT}/vmlinux \
	${VMLINUX_ADDITIONAL[@]}

# build in-tree modules
set -o pipefail
${_MAKE} -C ${EXTLIB_OUTPUT} CC="${CC}" modules

if [ -f "${EXTLIB_OUTPUT}/samples/ldk/.extract_kallsyms.o" ]; then
	export load_kallsyms_path=samples/ldk/load_kallsyms
	mkdir -p ${EXTLIB_OUTPUT}/${load_kallsyms_path}
	ln -sf ${EXTLIB_SRC}/${load_kallsyms_path}/* ${EXTLIB_OUTPUT}/${load_kallsyms_path}
	${_MAKE} -f ${EXTLIB_OUTPUT}/${load_kallsyms_path}/Makefile
	echo "${load_kallsyms_path}/load_kallsyms.ko" >> ${EXTLIB_OUTPUT}/modules.order
fi
